package net.xiaoyu233.mitemod.miteite.tileentity;

import net.minecraft.*;
import net.xiaoyu233.mitemod.miteite.block.Blocks;
import net.xiaoyu233.mitemod.miteite.tileentity.Recipes.RecyclingRecipes;
import net.xiaoyu233.mitemod.miteite.util.ParticleUtils;

public class TileEntityRecyclingTable extends TileEntity implements IWorldInventory {
    public boolean isUsing = false;
    private ItemStack[] recyclingSlots = new ItemStack[4]; // 0-1: 输入, 2-3: 输出

    // 添加回收进度相关变量
    private int recyclingProgress = 0;
    private int currentRecyclingTime = 0; // 当前回收所需时间
    private int baseRecyclingTime = 200; // 基础回收时间 (10秒)
    private boolean hasLava = false;
    private boolean[] slotInUse = new boolean[2]; // 标记哪个输入槽正在使用
    private int tableLevel = 0; // 回收台等级 (0: 铜, 1: 银, 2: 金, 3: 铁, 4: 秘银, 5: 精金, 6: 振金)

    @Override
    public int[] getSlotsForFace(int face) {
        return new int[]{0, 1, 2, 3}; // 0-1: 输入, 2-3: 输出
    }

    @Override
    public boolean canInsertItem(int slot, ItemStack itemStack, int side) {
        if (slot == 0 || slot == 1) {
            // 如果是上方（Y+方向），允许插入
            if (side == 1) {
                return isItemValidForSlot(slot, itemStack);
            }
            // 其他方向保持原有逻辑
            return isItemValidForSlot(slot, itemStack);
        }
        return false;
    }

    @Override
    public boolean canExtractItem(int slot, ItemStack itemStack, int side) {
        return slot == 2 || slot == 3; // 只能从输出槽提取
    }

    @Override
    public int getSizeInventory() {
        return recyclingSlots.length;
    }

    @Override
    public ItemStack getStackInSlot(int slot) {
        return recyclingSlots[slot];
    }

    @Override
    public ItemStack decrStackSize(int slot, int amount) {
        if (recyclingSlots[slot] != null) {
            ItemStack stack;
            if (recyclingSlots[slot].stackSize <= amount) {
                stack = recyclingSlots[slot];
                recyclingSlots[slot] = null;

                // 如果是输入槽被清空，重置对应的使用状态
                if (slot < 2) {
                    slotInUse[slot] = false;
                }
                return stack;
            } else {
                stack = recyclingSlots[slot].splitStack(amount);
                if (recyclingSlots[slot].stackSize == 0) {
                    recyclingSlots[slot] = null;
                    // 如果是输入槽被清空，重置对应的使用状态
                    if (slot < 2) {
                        slotInUse[slot] = false;
                    }
                }
                return stack;
            }
        }
        return null;
    }

    @Override
    public ItemStack getStackInSlotOnClosing(int slot) {
        if (recyclingSlots[slot] != null) {
            ItemStack stack = recyclingSlots[slot];
            recyclingSlots[slot] = null;

            // 如果是输入槽被清空，重置对应的使用状态
            if (slot < 2) {
                slotInUse[slot] = false;
            }
            return stack;
        }
        return null;
    }

    @Override
    public void setInventorySlotContents(int slot, ItemStack stack) {
        recyclingSlots[slot] = stack;
        if (stack != null && stack.stackSize > getInventoryStackLimit()) {
            stack.stackSize = getInventoryStackLimit();
        }

        // 当输入槽物品变化时，重新计算回收时间
        if (slot < 2) {
            if (stack != null) {
                slotInUse[slot] = true;
            } else {
                slotInUse[slot] = false;
            }

            // 检查是否有可回收的物品
            checkAndStartRecycling();
        }
    }

    private void checkAndStartRecycling() {
        // 检查两个输入槽是否有可回收的物品
        for (int i = 0; i < 2; i++) {
            if (recyclingSlots[i] != null && RecyclingRecipes.canRecycle(recyclingSlots[i], tableLevel) &&
                    (recyclingSlots[i + 2] == null || canMergeOutput(recyclingSlots[i], recyclingSlots[i + 2]))) {
                calculateRecyclingTime(recyclingSlots[i]);
                break;
            }
        }
    }

    private boolean canMergeOutput(ItemStack input, ItemStack output) {
        if (output == null) return true;
        Item ingot = RecyclingRecipes.getIngotForItem(input.getItem());
        return output.getItem() == ingot && output.stackSize < output.getMaxStackSize();
    }

    @Override
    public int getInventoryStackLimit() {
        return 64;
    }

    @Override
    public boolean isUseableByPlayer(EntityPlayer player) {
        return worldObj.getBlockTileEntity(xCoord, yCoord, zCoord) == this &&
                player.getDistanceSq(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5) <= 64.0;
    }

    @Override
    public void openChest() {

    }

    @Override
    public void closeChest() {
        this.isUsing = false;
    }

    @Override
    public boolean isItemValidForSlot(int slot, ItemStack stack) {
        if (slot < 2) { // 输入槽
            return RecyclingRecipes.canRecycle(stack, tableLevel);
        }
        return false; // 输出槽不能放置物品
    }

    @Override
    public void destroyInventory() {

    }
    public boolean hasLavaBelow( int x, int y, int z){
        if (worldObj == null) {
            return false;
        }
        Block blockAbove = worldObj.getBlock(x, y - 1, z);
        if (blockAbove != null && (blockAbove.blockID == Block.lavaStill.blockID  || blockAbove.blockID == Block.lavaMoving.blockID))  {
            return true;
        }
        return false;
    }

    @Override
    public void updateEntity() {
        if (!worldObj.isRemote) {
            // 检查下方是否有岩浆
            this.hasLava = this.hasLavaBelow( xCoord, yCoord, zCoord);

            if (!this.hasLava) {
                recyclingProgress = 0; // 没有岩浆则重置进度
                return;
            }
            // 检查上方是否有漏斗
            double smokeY = yCoord + 1.0;
            if (worldObj.getBlockTileEntity(xCoord, yCoord + 1, zCoord) instanceof TileEntityHopper) {
                smokeY = yCoord + 2.0; // 如果上方有漏斗，烟雾提高到漏斗上方
            }
            for (int i = 0; i < 5; i++) {
                ParticleUtils.spawnParticle(this.worldObj, EnumParticle.smoke.ordinal(),
                        xCoord + 0.5 + worldObj.rand.nextDouble() * 0.5 - 0.25,
                        smokeY,
                        zCoord + 0.5 + worldObj.rand.nextDouble() * 0.5 - 0.25,
                        0, 0.1, 0);
            }
            // 检查是否可以回收
            boolean canRecycle = false;
            for (int i = 0; i < 2; i++) {
                if (canRecycleSlot(i)) {
                    canRecycle = true;
                    break;
                }
            }

            if (canRecycle) {
                // 增加回收进度
                if (recyclingProgress < currentRecyclingTime) {
                    this.recyclingProgress++;
                    // 每完成10%进度播放一次声音
                    if (currentRecyclingTime > 0 && recyclingProgress % (currentRecyclingTime / 10) == 0) {
                        worldObj.playSoundEffect(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5,
                                "random.fizz", 0.5F, 1.0F);}

                } else {
                    // 回收完成，找到第一个可回收的槽位进行处理
                    for (int i = 0; i < 2; i++) {
                        if (canRecycleSlot(i)) {
                            recycleItem(i);
                            break;
                        }
                    }

                    recyclingProgress = 0; // 重置进度
                    currentRecyclingTime = 0; // 重置回收时间
                    // 检查是否还有其他物品需要回收
                    checkAndStartRecycling();

                    // 尝试将输出物品转移到相邻箱子
                    transferOutputToChests();


                }
            } else {
                recyclingProgress = 0; // 无法回收则重置进度
            }
        }
    }
    private void transferOutputToChests() {
        // 遍历六个方向，但只使用第一个找到的箱子
        for (int side = 2; side < 6; side++) {
            EnumFacing direction = EnumFacing.getFront(side);
            int targetX = xCoord + direction.getFrontOffsetX();
            int targetY = yCoord + direction.getFrontOffsetY();
            int targetZ = zCoord + direction.getFrontOffsetZ();

            TileEntity tileEntity = worldObj.getBlockTileEntity(targetX, targetY, targetZ);
            if (tileEntity instanceof IInventory && !(tileEntity instanceof TileEntityRecyclingTable)) {
                IInventory chest = (IInventory) tileEntity;
                // 尝试将两个输出槽的物品都放入这个箱子
                for (int i = 2; i <= 3; i++) {
                    if (recyclingSlots[i] != null) {
                        recyclingSlots[i] = tryPutStackInChest(chest, recyclingSlots[i]);
                    }
                }
                break; // 只处理第一个找到的箱子
            }
        }
    }

    // 尝试将物品堆叠放入箱子
    private ItemStack tryPutStackInChest(IInventory chest, ItemStack stack) {
        if (stack == null) return null;

        // 先尝试合并已有堆叠
        for (int i = 0; i < chest.getSizeInventory(); i++) {
            if (chest.isItemValidForSlot(i, stack)) {
                ItemStack chestStack = chest.getStackInSlot(i);

                if (chestStack != null && chestStack.getItem() == stack.getItem() &&
                        chestStack.getItemDamage() == stack.getItemDamage() &&
                        ItemStack.areItemStackTagsEqual(chestStack, stack)) {

                    int transferAmount = Math.min(chestStack.getMaxStackSize() - chestStack.stackSize, stack.stackSize);
                    if (transferAmount > 0) {
                        chestStack.stackSize += transferAmount;
                        stack.stackSize -= transferAmount;
                        chest.onInventoryChanged();

                        if (stack.stackSize <= 0) {
                            return null;
                        }
                    }
                }
            }
        }

        // 再尝试放入空槽
        for (int i = 0; i < chest.getSizeInventory(); i++) {
            if (chest.isItemValidForSlot(i, stack) && chest.getStackInSlot(i) == null) {
                chest.setInventorySlotContents(i, stack.copy());
                chest.onInventoryChanged();
                return null;
            }
        }

        return stack; // 箱子已满，返回剩余物品
    }

    public String getUnlocalizedInvName() {
        return this.getBlockType().getUnlocalizedName() + ".name";
    }

    private boolean canRecycleSlot(int slot) {
        return recyclingSlots[slot] != null &&
                RecyclingRecipes.canRecycle(recyclingSlots[slot], tableLevel) &&
                (recyclingSlots[slot + 2] == null || canMergeOutput(recyclingSlots[slot], recyclingSlots[slot + 2]));
    }

    // 根据物品耐久度计算回收时间
    private void calculateRecyclingTime(ItemStack stack) {
        if (stack == null) {
            currentRecyclingTime = 0;
            return;
        }

        int maxDurability = stack.getMaxDamage();
        int currentDurability = stack.getItemDamage();
        float durabilityRatio = 1.0f - (float) currentDurability / maxDurability;

        // 耐久度越高，回收时间越长
        currentRecyclingTime = (int) (baseRecyclingTime * (1 + durabilityRatio * 2));

        // 设置最小回收时间（至少20ticks，即1秒）
        currentRecyclingTime = Math.max(20, currentRecyclingTime);

        // 根据回收台等级调整回收时间
        float timeMultiplier = 1.0f - (tableLevel * 0.1f); // 每级减少10%回收时间
        currentRecyclingTime = (int) (currentRecyclingTime * timeMultiplier);
    }

    private int calculateMaterialCount(Item item, float durabilityRatio) {
        // 获取基础锭数量并转换为粒数量
        int baseCount = RecyclingRecipes.getBaseIngotCount(item) * 9;

        // 根据耐久度比例计算返还数量
        int count = (int) (baseCount * durabilityRatio);
        return Math.max(1, count); // 至少返还1个粒
    }
    private void recycleItem(int inputSlot) {
        ItemStack input = recyclingSlots[inputSlot];
        int outputSlot = inputSlot + 2; // 对应的输出槽

        if (RecyclingRecipes.canRecycle(input, tableLevel)) {
            Item ingot = RecyclingRecipes.getIngotForItem(input.getItem());
            Item nugget = RecyclingRecipes.getNuggetForItem(input.getItem());
            int maxDurability = input.getMaxDamage();
            int currentDurability = input.getItemDamage();
            float durabilityRatio = 1.0f - (float) currentDurability / maxDurability;

            // 计算返还的材料数量（以粒为单位）
            int materialCount = calculateMaterialCount(input.getItem(), durabilityRatio);

            // 根据回收台等级增加产量
            if (durabilityRatio < 0.8) {
                float yieldMultiplier = 1.0f + (tableLevel * 0.05f); // 每级增加5%产量
                materialCount = (int) (materialCount * yieldMultiplier);
            }
            // 确保至少返还1个粒
            materialCount = Math.max(1, materialCount);

            if (materialCount > 0) {
                // 计算完整的锭数量和剩余的粒数量
                int ingotCount = materialCount / 9;
                int nuggetCount = materialCount % 9;

                // 处理锭输出
                if (ingotCount > 0) {
                    if (recyclingSlots[outputSlot] == null) {
                        // 输出槽为空，创建新堆叠
                        recyclingSlots[outputSlot] = new ItemStack(ingot, ingotCount);
                    } else if (recyclingSlots[outputSlot].getItem() == ingot) {
                        // 输出槽已有同种锭，增加数量
                        recyclingSlots[outputSlot].stackSize += ingotCount;
                    } else {
                        // 输出槽有不同物品，尝试放入下一个输出槽
                        int nextOutputSlot = (outputSlot == 2) ? 3 : 2;
                        if (recyclingSlots[nextOutputSlot] == null) {
                            recyclingSlots[nextOutputSlot] = new ItemStack(ingot, ingotCount);
                        } else if (recyclingSlots[nextOutputSlot].getItem() == ingot) {
                            recyclingSlots[nextOutputSlot].stackSize += ingotCount;
                        } else {
                            // 两个输出槽都有不同物品，无法放置，跳过
                            ingotCount = 0;
                        }
                    }
                }

                // 处理粒输出
                if (nuggetCount > 0) {
                    int targetSlot = outputSlot;

                    // 如果第一个输出槽已有物品但不是粒，尝试第二个输出槽
                    if (recyclingSlots[outputSlot] != null && recyclingSlots[outputSlot].getItem() != nugget) {
                        targetSlot = (outputSlot == 2) ? 3 : 2;
                    }

                    if (recyclingSlots[targetSlot] == null) {
                        // 输出槽为空，创建新堆叠
                        recyclingSlots[targetSlot] = new ItemStack(nugget, nuggetCount);
                    } else if (recyclingSlots[targetSlot].getItem() == nugget) {
                        // 输出槽已有同种粒，增加数量
                        recyclingSlots[targetSlot].stackSize += nuggetCount;
                    } else if (recyclingSlots[targetSlot].getItem() == ingot && ingotCount == 0) {
                        // 如果输出槽是锭且没有锭输出，尝试将锭转换为粒
                        int totalNuggets = recyclingSlots[targetSlot].stackSize * 9 + nuggetCount;
                        int newIngotCount = totalNuggets / 9;
                        int newNuggetCount = totalNuggets % 9;

                        if (newIngotCount > 0) {
                            recyclingSlots[targetSlot] = new ItemStack(ingot, newIngotCount);
                            if (newNuggetCount > 0) {
                                // 需要将多余的粒放入另一个槽
                                int otherSlot = (targetSlot == 2) ? 3 : 2;
                                if (recyclingSlots[otherSlot] == null) {
                                    recyclingSlots[otherSlot] = new ItemStack(nugget, newNuggetCount);
                                } else if (recyclingSlots[otherSlot].getItem() == nugget) {
                                    recyclingSlots[otherSlot].stackSize += newNuggetCount;
                                }
                            }
                        } else {
                            recyclingSlots[targetSlot] = new ItemStack(nugget, newNuggetCount);
                        }
                    }
                }

                // 消耗输入物品
                recyclingSlots[inputSlot] = null;
                slotInUse[inputSlot] = false;

                worldObj.playSoundEffect(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5,
                        "random.anvil_use", 1.0F, 1.0F);
            }
        }
    }

    @Override
    public void readFromNBT(NBTTagCompound nbt) {
        super.readFromNBT(nbt);
        NBTTagList items = nbt.getTagList("Items");
        recyclingSlots = new ItemStack[getSizeInventory()];

        for (int i = 0; i < items.tagCount(); i++) {
            NBTTagCompound item = (NBTTagCompound) items.tagAt(i);
            byte slot = item.getByte("Slot");

            if (slot >= 0 && slot < recyclingSlots.length) {
                recyclingSlots[slot] = ItemStack.loadItemStackFromNBT(item);
                if (slot < 2 && recyclingSlots[slot] != null) {
                    slotInUse[slot] = true;
                }
            }
        }

        // 读取回收进度和时间
        recyclingProgress = nbt.getInteger("RecyclingProgress");
        currentRecyclingTime = nbt.getInteger("CurrentRecyclingTime");
        tableLevel = nbt.getInteger("TableLevel");
        this.hasLava = nbt.getBoolean("HasLava");
        // 读取槽位使用状态
        byte[] slotUsage = nbt.getByteArray("SlotUsage");
        if (slotUsage.length >= 2) {
            for (int i = 0; i < 2; i++) {
                slotInUse[i] = slotUsage[i] != 0;
            }
        }

    }

    @Override
    public void writeToNBT(NBTTagCompound nbt) {
        super.writeToNBT(nbt);
        NBTTagList items = new NBTTagList();

        for (int i = 0; i < recyclingSlots.length; i++) {
            if (recyclingSlots[i] != null) {
                NBTTagCompound item = new NBTTagCompound();
                item.setByte("Slot", (byte) i);
                recyclingSlots[i].writeToNBT(item);
                items.appendTag(item);
            }
        }

        nbt.setTag("Items", items);

        // 保存回收进度和时间
        nbt.setInteger("RecyclingProgress", recyclingProgress);
        nbt.setInteger("CurrentRecyclingTime", currentRecyclingTime);
        nbt.setInteger("TableLevel", tableLevel);
        nbt.setBoolean("HasLava",  this.hasLava);
        // 保存槽位使用状态
        byte[] slotUsage = new byte[2];
        for (int i = 0; i < 2; i++) {
            slotUsage[i] = (byte) (slotInUse[i] ? 1 : 0);
        }
        nbt.setByteArray("SlotUsage", slotUsage);
    }

//    @Override
//    public void onInventoryChanged() {
//        super.onInventoryChanged();
//
//    }

    // 获取回收进度（用于GUI显示）
    public int getRecyclingProgress() {
        return recyclingProgress;
    }

    // 获取当前回收所需时间（用于GUI显示）
    public int getCurrentRecyclingTime() {
        return currentRecyclingTime;
    }

    // 检查是否有岩浆（用于GUI显示）
    public boolean hasLava() {
        return hasLava;
    }

    // 获取物品耐久度信息（用于GUI显示）
    public String getDurabilityInfo(int slot) {
        if (slot < 0 || slot >= 2 || recyclingSlots[slot] == null) return "";

        int maxDurability = recyclingSlots[slot].getMaxDamage();
        int currentDurability = recyclingSlots[slot].getItemDamage();
        float durabilityRatio = 1.0f - (float) currentDurability / maxDurability;
        int durabilityPercent = (int) (durabilityRatio * 100);

        return durabilityPercent + "% 耐久度";
    }

    // 检查槽位是否正在使用
    public boolean isSlotInUse(int slot) {
        return slot >= 0 && slot < 2 && slotInUse[slot];
    }

    public void setRecyclingProgress(int progress) {
        this.recyclingProgress = progress;
    }

    // 添加设置当前回收时间的方法（用于客户端）
    public void setCurrentRecyclingTime(int time) {
        this.currentRecyclingTime = time;
    }

    public void setHasLava(boolean hasLava){
        this.hasLava = hasLava;
    }

    // 获取和设置回收台等级
    public int getTableLevel() {
        return tableLevel;
    }

    public void setTableLevel(int level) {
        this.tableLevel = level;
    }

    // 获取回收台等级名称
    public String getTableLevelName() {
        switch (tableLevel) {
            case 0: return "铜";
            case 1: return "银";
            case 2: return "金";
            case 3: return "铁";
            case 4: return "秘银";
            case 5: return "远古金属";
            case 6: return "艾德曼";
            case 7: return "振金";
            default: return "未知";
        }
    }
}